home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d11 / nansi22b.arc / NANSI_F.ASM < prev    next >
Assembly Source File  |  1987-12-03  |  17KB  |  639 lines

  1.     page    66, 132
  2. ;----- nansi_f.asm ---------------------------------------------
  3. ; The ANSI control subroutines.
  4. ; (C) 1986 Daniel Kegel, Pasadena, CA
  5. ; May be distributed for educational and personal use only
  6. ; Each routine is called with the following register usage:
  7. ;  AX = max(1, value of first parameter)
  8. ;  Z flag is set if first parameter is zero.
  9. ;  CX = number of paramters
  10. ;  SI = offset of second parameter from CS
  11. ;  DS = CS
  12. ;  ES:DI points to the current location on the memory-mapped screen.
  13. ;  DX is number of characters remaining on the current screen line.
  14. ; The control routine is free to trash AX, BX, CX, SI, and DS.
  15. ; It must preserve ES, and can alter DX and DI if it wants to move the
  16. ; cursor.
  17. ;
  18. ; Revisions:
  19. ;  19 Aug 85: Fixed horrible bug in insert/delete line.
  20. ;  26 Aug 85: Fixed simple limit-to-one-too-few-lines bug in ins/del line;
  21. ;  anyway, it inserts 24 lines when on line 2 now.  Whether it's fixed...
  22. ;  4 Sept 85: Fixed bug created on 26 Aug 85; when limiting ins/del line
  23. ;  count, we are clearing, not scrolling; fixed BIOS call to reflect this.
  24. ;  30 Jan 86: Added EGA cursor patch
  25. ;  31 Jan 86: Disabled insert/delete char in graphics modes
  26. ;          Implemented keyboard redefinition reset
  27. ;  1 Feb 86: added video_mode and max_x test after mode set
  28. ;----------------------------------------------------------------
  29.  
  30.     include nansi_d.asm
  31.  
  32.                     ; To nansi_p.asm
  33.     public    ansi_fn_table
  34.  
  35.                     ; From nansi.asm
  36.     extrn    port_6845:word
  37.     extrn    cur_coords:word, saved_coords:word
  38.     extrn    cur_x:byte, max_x:byte
  39.     extrn    cur_y:byte, max_y:byte
  40.     extrn    cur_attrib:byte, wrap_flag:byte
  41.     extrn    xy_to_regs:near
  42.     extrn    get_blank_attrib:near
  43.     extrn    xlate_tab_ptr:word
  44.     extrn    cpr_esc:byte, cprseq:word
  45.     extrn    video_mode:byte
  46.     extrn    lookup:near
  47.     extrn    in_g_mode:near
  48.  
  49.                     ; from nansi_p.asm
  50.     extrn    param_buffer:word    ; used in keyboard programming
  51.     extrn    param_end:word
  52.     extrn    redef_end:word
  53.  
  54. keybuf    struc                ; used in making cpr sequence
  55. len    dw    ?
  56. adr    dw    ?
  57. keybuf    ends
  58.  
  59.  
  60. ABS40    segment at 40h
  61.     org    1ah
  62. buffer_head dw    ?            ; Used in 'flush input buffer' dos call.
  63. buffer_tail dw    ?
  64.  
  65.     org    49h
  66. crt_mode db    ?
  67. crt_cols dw    ?
  68. crt_len dw    ?
  69. crt_start dw    ?
  70. cursor_posn dw    8 dup (?)
  71. cursor_mode dw    ?
  72. active_page db    ?
  73. addr_6845 dw    ?
  74. crt_mode_set db ?
  75. crt_palette db    ?
  76.  
  77. ABS40    ends
  78.  
  79. code    segment byte public 'CODE'
  80.     assume    cs:code, ds:code
  81.  
  82. ;----- byteout ---------------------------------------------------
  83. ; Converts al to a decimal ASCII string (in 0..99),
  84. ; stores it at ES:DI++.  Returns DI pointing at byte after last digit.
  85. ; Destroys DL.
  86.  
  87. byteout proc    near
  88.     aam
  89.     add    ax, 3030h
  90.     xchg    ah, al
  91.     stosb
  92.     xchg    ah, al
  93.     stosb
  94.     ret
  95. byteout endp
  96.  
  97. ;----- ansi_fn_table -----------------------------------
  98. ; Table of offsets of terminal control subroutines in order of
  99. ; the character that invokes them, @..Z, a..z.    Exactly 53 entries.
  100. ; All the subroutines are defined below in this module.
  101. ansi_fn_table label word
  102.     dw    ic,  cup, cdn, cfw, cbk ; @, A, B, C, D
  103.     dw    nul, nul, nul, hvp, nul ; E, F, G, H, I
  104.     dw    eid, eil, il,  d_l, nul ; J, K, L, M, N
  105.     dw    nul, dc,  nul, nul, nul ; O, P, Q, R, S
  106.     dw    nul, nul, nul, nul, nul ; T, U, V, W, X
  107.     dw    nul, nul        ; Y, Z
  108.     dw    nul, nul, nul, nul, nul ; a, b, c, d, e
  109.     dw    hvp, nul, sm,  nul, nul ; f, g, h, i, j
  110.     dw    nul, rm,  sgr, dsr, nul ; k, l, m, n, o
  111.     dw    key, nul, nul, scp, nul ; p, q, r, s, t
  112.     dw    rcp, nul, nul, nul, xoc ; u, v, w, x, y
  113.     dw    nul            ; z
  114.  
  115. ansi_functions proc near        ; set return type to NEAR
  116.  
  117. ;----- nul ---------------------------------------------
  118. ; No-action ansi sequence; called when unknown command given.
  119. nul:    ret
  120.  
  121. ;----- Cursor Motion -----------------------------------------------
  122.  
  123. ;-- cursor to y,x
  124. hvp:    or    al, al            ; First parameter is desired Y coordinate.
  125.     jz    hvp_yok
  126.     dec    ax            ; Convert to zero-based coordinates.
  127. hvp_yok:mov cur_y, al
  128.                     ; Get second parameter, if it is there, and set X with it.
  129.     xor    ax, ax
  130.     cmp    cx, 2            ; was there a second parameter?
  131.     jb    hvp_xok
  132.     lodsb                ; yes.
  133.     or    al, al
  134.     jz    hvp_xok
  135.     dec    ax            ; convert to zero-based coordinates.
  136. hvp_xok:mov cur_x, al
  137.  
  138.                     ; Clip to maximum coordinates.
  139. hvp_set:
  140.     mov    ax, cur_coords        ; al = x, ah = y
  141.     cmp    al, max_x
  142.     jbe    hvp_sxok
  143.     mov    al, max_x
  144.     mov    cur_x, al
  145. hvp_sxok:
  146.     cmp    ah, max_y
  147.     jbe    hvp_syok
  148.     mov    al, max_y
  149.     mov    cur_y, al
  150. hvp_syok:
  151.                     ; Set values of DX and DI accordingly.
  152.     call    xy_to_regs
  153.     ret
  154.  
  155. ;-- cursor forward --
  156. cfw:    add    cur_x, al
  157.     jmp    hvp_set
  158.  
  159. ;-- cursor back -----
  160. cbk:    sub    cur_x, al
  161.     jae    cbk_ok
  162.     mov    cur_x, 0
  163. cbk_ok: jmp    hvp_set
  164.  
  165. ;-- cursor down -----
  166. cdn:    add    cur_y, al
  167.     jmp    hvp_set
  168.  
  169. ;-- cursor up -------
  170. cup:    sub    cur_y, al
  171.     jae    cup_ok
  172.     mov    cur_y, 0
  173. cup_ok: jmp    hvp_set
  174.  
  175. ;-- save cursor position --------------------------------------
  176. scp:    mov    ax, cur_coords
  177.     mov    saved_coords, ax
  178.     ret
  179.  
  180. ;-- restore cursor position -----------------------------------
  181. rcp:    mov    ax, saved_coords
  182.     mov    cur_coords, ax
  183.     jmp    hvp_set         ; Clip in case we have switched video modes.
  184.  
  185. ;-- set graphics rendition ------------------------------------
  186. ; Modifies the color in which new characters are written.
  187.  
  188. sgr:    dec    si            ; get back pointer to first parameter
  189.     or    cx, cx            ; Did he give any parameters?
  190.     jnz    sgr_loop
  191.     mov    byte ptr [si], 0    ; no parameters, so fake
  192.     inc    cx            ; one with the default value.
  193.                     ; For each parameter
  194. sgr_loop:
  195.     lodsb                ; al = next parameter
  196.                     ; Search color table
  197.     push    cx
  198.     mov    cx, colors
  199.     mov    bx, offset color_table-3
  200. sgr_search:
  201.     add    bx, 3
  202.     cmp    al, byte ptr [bx]
  203.     loopnz    sgr_search        ; until match found or done
  204.     jnz    sgr_loopx
  205.  
  206.                     ; If parameter named a known color, set the current
  207.                     ; color variable.
  208.     mov    ax, [bx+1]
  209.     and    cur_attrib, al
  210.     or    cur_attrib, ah
  211. sgr_loopx:
  212.     pop    cx
  213.     loop    sgr_loop        ; until no more parameters.
  214.     ret
  215.  
  216. ;-- erase in line ----------------------------------------
  217. ; Uses BIOS to scroll away a one-line rectangle
  218. eil:    push    dx
  219.     mov    cx, cur_coords
  220.     mov    dh, ch
  221.     jmp    short scrollem
  222.  
  223. ;-- erase in display -------------------------------------
  224. ; Uses BIOS to scroll away all of display
  225. eid:    cmp    al, 2
  226.     jnz    eid_ignore        ; param must be two
  227.     IF    cls_homes_too
  228.         mov     cur_coords, 0
  229.         call    xy_to_regs
  230.     ENDIF
  231.     push    dx
  232.     xor    cx, cx
  233.     mov    dh, max_y
  234. scrollem:
  235.     call    get_blank_attrib
  236.     mov    bh, ah
  237.     mov    dl, max_x
  238.     mov    ax, 600h
  239.     int    10h
  240.     pop    dx
  241. eid_ignore:
  242.     ret
  243.  
  244. ;-- device status report --------------------------------
  245. ; Stuffs an escape, a left bracket, current Y, semicolon, current X,
  246. ; a capital R, and a carriage return into input stream.
  247. ; The coordinates are 1 to 3 decimal digits each.
  248.  
  249. dsr:    push    di
  250.     push    dx
  251.     push    es
  252.     mov    ax, cs
  253.     mov    es, ax
  254.     std                ; Store string in reversed order for fun
  255.     mov    di, offset cpr_esc - 2
  256.     mov    al, cur_y
  257.     inc    al            ; convert to one-based coords
  258.     call    byteout         ; row
  259.     mov    al, ';'         ; ;
  260.     stosb
  261.     mov    al, cur_x
  262.     inc    al            ; convert to one-based coords
  263.     call    byteout         ; column
  264.     mov    al, 'R'         ; R ANSI function 'Cursor Position Report'
  265.     stosb
  266.     mov    al, 13
  267.     mov    word ptr cprseq.adr, di ; save pointer to last char in string
  268.     stosb                ; send a carriage return, too
  269.     mov    ax, offset cpr_esc
  270.     sub    ax, di            ; ax is # of characters in string
  271.     mov    word ptr cprseq.len, ax ; pass info to the getchar routine
  272.     cld
  273.     pop    es
  274.     pop    dx
  275.     pop    di
  276.     ret
  277.  
  278. ;-- keyboard reassignment -------------------------------
  279. ; Key reassignment buffer is between param_end and redef_end+2, exclusive.
  280. ; When it shrinks or grows, param_end is moved.
  281. ; Format of an entry is as follows:
  282. ;   highest address -> length:word (may be 0)
  283. ;               key to replace:word     (either hi or low byte is zero)
  284. ;               .
  285. ;               .    new key value, "length" bytes long
  286. ;               .
  287. ;   lowest address  -> next entry, or free space.
  288. ; If no arguments are given, keyboard is reset to default condition.
  289. ; Otherwise, first parameter (or first two, if first is zero) defines
  290. ; the key whose value is to be changed, and the following parameters
  291. ; define the key's new, possibly zero-length, value.
  292.  
  293. key:
  294.                     ; Is this a reset?
  295.     or    cx, cx
  296.     jz    key_init
  297.                     ; Get the first (or first two) parameters
  298.     cld
  299.     dec    si            ; point to first param
  300.     dec    cx            ; Assume it's a fn key, get two params
  301.     dec    cx
  302.     lodsw
  303.     or    al, al            ; Is it a function key?
  304.     jz    key_fnkey
  305.                     ; It's not a function key- put second param back
  306.     inc    cx
  307.     dec    si
  308. key_fnkey:
  309.                     ; Key to redefine now in AX.  If it's already redefined,
  310.                     ; lookup will set Z, point SI to redef string, set CX to its length.
  311.     push    di
  312.     push    es
  313.     push    cx
  314.     push    si
  315.  
  316.     std                ; moving up, must move from top down
  317.     push    ds
  318.     pop    es            ; string move must have ES=DS
  319.     call    lookup            ; rets Z if redefined...
  320.     jnz    key_newkey
  321.                     ; It's already defined.  Erase its old definition- i.e., move
  322.                     ; region param_end+1..SI-1 upwards CX+4 bytes, add CX+4 to param_end.
  323.     add    cx, 4
  324.     mov    bp, param_end        ; save old value in bp...
  325.     add    param_end, cx
  326.     dec    si            ; start at (SI-1)
  327.     mov    di, si
  328.     add    di, cx            ; move to (start + CX+4)
  329.     mov    cx, si
  330.     sub    cx, bp            ; length of region old_param_end+1..start
  331.     rep    movsb
  332. key_newkey:
  333.                     ; Key not redefined.  See if there's enough room to redefine it.
  334.     pop    si            ; get back pointer to redef string
  335.     pop    cx            ; get back number of bytes in redef string
  336.     mov    di, param_end        ; hi byte of new redef record, hi byte of len
  337.     sub    di, 4            ; hi byte of new data field
  338.     mov    bx, di
  339.     sub    bx, cx            ; hi byte of remaining buffer space
  340.     sub    bx, 16            ; better be at least 16 bytes room
  341.     cmp    bx, param_buffer
  342.     jb    key_popem        ; nope- forget it.
  343.                     ; Nothing in the way now!
  344.     mov    [di+3], cx        ; save length field
  345.     mov    [di+1], ax        ; save name field
  346.     jcxz    key_nullstring
  347. key_saveloop:                ; save data field
  348.     movsb
  349.     add    si, 2            ; input string ascending, output descending
  350.     loop    key_saveloop
  351. key_nullstring:
  352.     mov    param_end, di        ; save adr of new hi byte of free area
  353. key_popem:
  354.     pop    es
  355.     pop    di
  356.  
  357. key_exit:
  358.     cld
  359.     ret
  360.  
  361. key_init:
  362.                     ; Build the default redefinition table:
  363.                     ;    control-printscreen -> control-P
  364.     push    es
  365.     push    ds
  366.     pop    es
  367.     std
  368.     mov    di, redef_end
  369.     mov    ax, 1
  370.     stosw
  371.     mov    ax, 7200h        ; control-printscreen
  372.     stosw
  373.     mov    al, 16            ; control P
  374.     stosb
  375.     mov    param_end, di        ; save new bottom of redef table
  376.     pop    es
  377.     jmp    key_exit
  378.  
  379. ;---- Delete/Insert Lines -------------------------------
  380. ; AL is number of lines to delete/insert.
  381. ; Preserves DX, DI; does not move cursor.
  382.  
  383. d_l:                    ; Delete lines.
  384.     mov    ah, 6            ; BIOS: scroll up
  385.     jmp    short il_open
  386.  
  387. il:                    ; Insert lines.
  388.     mov    ah, 7            ; BIOS: scroll down
  389.  
  390. il_open:
  391.                     ; Whether inserting or deleting, limit him to (max_y - cur_y) lines;
  392.                     ; if above that, we're just clearing; set AL=0 so BIOS doesn't burp.
  393.     mov    bh, max_y
  394.     sub    bh, cur_y
  395.     cmp    al, bh
  396.     jbe    il_ok            ; DRK 9/4...
  397.     mov    al, 0            ; he tried to move too far
  398. il_ok:
  399.     push    ax
  400.     call    get_blank_attrib
  401.     mov    bh, ah            ; color to use on new blank areas
  402.     pop    ax            ; AL is number of lines to scroll.
  403.  
  404.     mov    cl, 0            ; upper-left-x of data to scroll
  405.     mov    ch, cur_y        ; upper-left-y of data to scroll
  406.     push    dx
  407.     mov    dl, max_x        ; lower-rite-x
  408.     mov    dh, max_y        ; lower-rite-y (zero based)
  409.     int    10h            ; call BIOS to scroll a rectangle.
  410.     pop    dx
  411.     ret                ; done.
  412.  
  413. ;-- Insert / Delete Characters ----------------------------
  414. ; AL is number of characters to insert or delete.
  415. ; Preserves DX, DI; does not move cursor.
  416.  
  417. ic:    mov    ch, 1            ; 1 => swap dest & source below
  418.     jmp    short dc_ch
  419.  
  420. dc:    mov    ch, 0
  421.  
  422. dc_ch:
  423.     call    in_g_mode
  424.     jnc    dc_ret            ; | if in graphics mode, ignore.
  425.  
  426.                     ; AL = number of chars to ins or del (guarenteed nonzero).
  427.                     ; Limit him to # of chars left on line.
  428.     cmp    al, dl
  429.     jbe    dc_cok
  430.     mov    al, dl
  431. dc_cok:
  432.     push    di            ; DI is current address of cursor
  433.     xchg    ax, cx            ; CX gets # of chars to ins/del
  434.     mov    bp, cx            ; BP gets # of columns to clear.
  435.  
  436.                     ; Set up source = destination + cx*2, count = dx - cx
  437.     mov    ch, 0            ; make it a word
  438.     mov    si, di
  439.     add    si, cx
  440.     add    si, cx
  441.     neg    cl
  442.     add    cl, dl
  443.     mov    ch, 0            ; CX = # of words to transfer
  444.     cld                ; REP increments si & di
  445.  
  446.                     ; If this is an insert, then flip transfer around in both ways.
  447.     test    ah, 1
  448.     jz    dc_noswap
  449.     xchg    di, si            ; source <-> dest
  450.     std                ; up <-> down
  451.     mov    ax, cx            ; make move over same range
  452.     dec    ax
  453.     add    ax, ax            ; AX=dist from 1st to last byte.
  454.     add    di, ax            ; Start transfer at high end of block
  455.     add    si, ax            ;  instead of low end.
  456. dc_noswap:
  457.                     ; Move those characters.
  458.     push    es
  459.     pop    ds
  460.     rep    movsw
  461.     mov    cx, bp
  462.                     ; Figure out what color to make the new blanks.
  463.     call    get_blank_attrib
  464.     mov    al, ' '
  465.                     ; Blank out vacated region.
  466.     rep    stosw
  467.  
  468.                     ; All done.
  469.     cld                ; restore normal REP state and
  470.     pop    di            ;  cursor address.
  471. dc_ret: ret
  472.  
  473.  
  474. ;---- set / reset mode ---------------------------------------
  475. ; Sets graphics/text mode; also sets/resets "no wrap at eol" mode.
  476. sm:    mov    cl, 0ffh        ; set
  477. sm_rs:
  478.                     ; Is it "wrap at eol" ?
  479.     cmp    al, 7
  480.     jnz    sm_notwrap
  481.     mov    wrap_flag, cl        ; true = wrap at EOL
  482.     jmp    short sm_done
  483. sm_notwrap:
  484.                     ; Is it "set highest number of screen lines available"?
  485.     cmp    al, 43
  486.     jnz    sm_video
  487.                     ; Only valid for the Enhanced Graphics Adaptor on
  488.                     ; a monochrome display or an enhanced color display.
  489.                     ; Test presence of EGA by calling BIOS fn 12h.10h.
  490.     mov    ah, 12h
  491.     mov    bx, 0ff10h
  492.     int    10h            ; bh=0-1, bl=0-3 if EGA
  493.     test    bx, 0FEFCH
  494.     jnz    sm_done         ; sorry, charlie
  495. ;        mov    port_6845, 3d4h
  496. ;        mov    al, video_mode
  497. ;        and    al, 7
  498. ;        cmp    al, 7            ; monochrome monitor?
  499. ;        jnz    sm_colormon
  500. ;            mov    byte ptr port_6845, low(3b4h)
  501. ;sm_colormon:
  502.                     ; 43 line mode only allowed in text modes, for now.
  503.     call    in_g_mode
  504.     jnc    sm_done
  505.  
  506.     mov    ah, 0            ; "Set video mode"
  507.     mov    al, video_mode        ; Re-init current mode
  508.     int    10h
  509.  
  510.     mov    ax,1112h        ; Load 8x8 font
  511.     mov    bl,0            ; (instead of 8x14)
  512.     int    10h
  513.  
  514.     mov    ax, 1200h        ; Load new printscreen
  515.     mov    bl, 20h
  516.     int    10h
  517.  
  518.     mov    ah,1
  519.     mov    cx,0707h        ; (Load cursor scan lines)
  520.     int    10h
  521.                     ; | Patch; this gotten by painful observation of
  522.                     ; | IBM's professional editor.  I think there's a
  523.                     ; | documented bug in Video Bios's "load cursor scan line"
  524.                     ; | call; try looking in latter 1985 PC Tech Journal.
  525.     mov    dx, port_6845        ; '6845' command reg
  526.     mov    al, 10
  527.     out    dx, al
  528.     jmp    $+2
  529.     inc    dx
  530.     mov    al, 7
  531.     out    dx, al            ; set cursor start line
  532.                     ; Assume that gets us 43 lines.
  533.     mov    max_y, 42
  534.     jmp    short sm_home
  535. sm_video:
  536.                     ; It must be a video mode.  Call BIOS.
  537.     mov    ah, 0            ; "set video mode"
  538.     int    10h
  539.                     ; Assume that gets us 25 lines.
  540.     mov    max_y, 24
  541. sm_home:
  542.                     ; Read the BIOS buffer address/cursor position variables.
  543.     mov    ax, abs40
  544.     push    ds
  545.     mov    ds, ax
  546.     assume    ds:abs40
  547.                     ; Find current video mode and screen size.
  548.     mov    ax,word ptr crt_mode    ; al = crt mode; ah = # of columns
  549.     pop    ds
  550.     mov    video_mode, al
  551.     dec    ah            ; ah = max column
  552.     mov    max_x, ah
  553.  
  554.                     ; Since cursor may end up in illegal position, it's best to
  555.                     ; just go home after switching video modes.
  556.     mov    cur_coords, 0
  557.     call    xy_to_regs
  558. sm_done:
  559.     ret
  560.  
  561. rm:    mov    cl, 0            ; reset
  562.     jmp    sm_rs
  563.  
  564. ;------- Output Character Translation ----------------------
  565. ; A decidedly nonstandard function, possibly useful for editing files
  566. ; intended to be printed by daisywheel printers with strange wheels.
  567. ; (The letter 'y' was chosen to conflict with the VT100 self-test command.)
  568. ; Usage: ESC [ #1;#2 y
  569. ; where #1 is the character to redefine
  570. ;    #2 is the new display value
  571. ; If only ESC [ #1 y is sent, character #1 is reset to its default value.
  572. ; If only ESC [ y is sent, the entire table is reset to the default value.
  573. ; (If only ESC [ #1; y is sent, character #1 is set to zero... sigh.)
  574.  
  575. xoc:                    ; Xlate output character
  576.     mov    bx, xlate_tab_ptr
  577.     jcxz    xoc_reset        ; if no parameters, reset table to 1:1
  578.     dec    si            ; point to first parameter
  579.     lodsw                ; first parameter to AL, second to AH
  580.     dec    cx            ; is parameter count 1?
  581.     jnz    xoc_bothparams
  582.     mov    ah, al            ; if only one param, reset that char.
  583. xoc_bothparams:
  584.     add    bl, al
  585.     adc    bh, 0            ; bx points to entry for char AL
  586.     mov    byte ptr [bx], ah    ; change that entry
  587. xoc_done:
  588.     ret
  589.  
  590. xoc_reset:
  591.                     ; Fill table with default values- i.e. 0, 1, 2, ... 255.
  592.     xor    ax, ax
  593. xoc_loop:
  594.     mov    byte ptr [bx], al
  595.     inc    bx
  596.     inc    al
  597.     jnz    xoc_loop
  598.     jmp    xoc_done
  599.  
  600. ansi_functions endp            ; end dummy procedure block
  601.  
  602.  
  603.  
  604. ;-------- Color table -----------------------------------------
  605. ; Used in "set graphics rendition"
  606. colors    equ    22            ; number of colors in table
  607. color_table:
  608.     db    0, 000h,07h        ; all attribs off; normal.
  609.     db    1, 0ffh,08h        ; bold
  610.     db    4, 0f8h,01h        ; underline
  611.     db    5, 0ffh,80h        ; blink
  612.     db    7, 0f8h,70h        ; reverse
  613.     db    8, 088h,00h        ; invisible
  614.  
  615.     db    30,0f8h,00h        ; black foreground
  616.     db    31,0f8h,04h        ; red
  617.     db    32,0f8h,02h        ; green
  618.     db    33,0f8h,06h        ; yellow
  619.     db    34,0f8h,01h        ; blue
  620.     db    35,0f8h,05h        ; magenta
  621.     db    36,0f8h,03h        ; cyan
  622.     db    37,0f8h,07h        ; white
  623.  
  624.     db    40,08fh,00h        ; black background
  625.     db    41,08fh,40h        ; red
  626.     db    42,08fh,20h        ; green
  627.     db    43,08fh,60h        ; yellow
  628.     db    44,08fh,10h        ; blue
  629.     db    45,08fh,50h        ; magenta
  630.     db    46,08fh,30h        ; cyan
  631.     db    47,08fh,70h        ; white
  632.  
  633.  
  634. code    ends
  635.     end                ; of nansi_f.asm
  636.  
  637. lue
  638.     db    45,08fh,50h        ; magenta
  639.     db    46,08fh,30h